#ifndef CONJHEAP_H
#define CONJHEAP_H

#include "aed2.h"

#include "auxiliares.h"


using namespace aed2;
class conjheap
{
    public:

        conjheap();
        conjheap(Nat);

		Nat Cardinal();
        void Agregar(InfoCliente&);
        InfoCliente Sacar();

        Lista<InfoCliente>::Iterador DameElementos();

        InfoCliente dame(int);
        bool operator==(const conjheap&) const;

    private:

        Nat cardinal;
        Nat tam;

        Lista<InfoCliente> elems;

        Arreglo<InfoCliente> pDatos;

        typedef aed2::Lista<InfoCliente> ListaS;
};

conjheap::conjheap(Nat n) {

    Arreglo<InfoCliente> aux(n);
    this->pDatos = aux;
    this->tam = n;
    this->cardinal = 0;
}


conjheap::conjheap() {

    this->tam = 0;
    this->cardinal = 0;
}

Nat conjheap::Cardinal(){

		return cardinal;
}

InfoCliente conjheap::dame(int i){
    return this->pDatos[i];
}

void conjheap::Agregar(InfoCliente& dato){

    cardinal++;
    int aux = 0;
    int i = 0;

    InfoCliente auxVar;

    if (cardinal <= tam) {

        pDatos.Definir(cardinal -1,dato);
        i = cardinal - 1;

        while (i > 0) {

            if (i % 2 == 0) {
                aux = (i - 2) / 2;

                if (pDatos[i].n >pDatos[aux].n) {

                    auxVar = pDatos[aux];

                    pDatos.Definir(aux,pDatos[i]);
                    pDatos.Definir(i,auxVar);
                }

                i = aux;

            } else {

                aux = (i - 1) / 2;

                if (pDatos[i].n >pDatos[aux].n) {

                    auxVar = pDatos[aux];

                    pDatos.Definir(aux,pDatos[i]);
                    pDatos.Definir(i,auxVar);

                }

                i = aux;

            }

        }

    } else {

        Lista<InfoCliente>::Iterador itLista;

        itLista = DameElementos();

        Arreglo<InfoCliente> auxNuevo(cardinal);
        pDatos = auxNuevo;

        i = 0;
        while (i < cardinal) {

            pDatos.Definir(i, itLista.Siguiente());
            itLista.Avanzar();
        }

        pDatos.Definir(cardinal - 1,dato);
        i = cardinal - 1;

        while (i > 0) {
            if (i % 2 == 0) {
                aux = (i - 2) / 2;
                if (pDatos[i].n >pDatos[aux].n) {

                    auxVar = pDatos[aux];

                    pDatos.Definir(aux,pDatos[i]);
                    pDatos.Definir(i,auxVar);

                }

                i = aux;

            } else {

                aux = (i - 1) / 2;

                if (pDatos[i].n >pDatos[aux].n) {

                    auxVar = pDatos[aux];

                    pDatos.Definir(aux,pDatos[i]);
                    pDatos.Definir(i,auxVar);

                }
                i = aux;
            }
        }
    }
}

InfoCliente conjheap::Sacar(){

    InfoCliente aux  = pDatos[0];
    
    pDatos.Definir(0,pDatos[cardinal - 1]);

    cardinal--;
    Nat i = 0;
    InfoCliente bufVar;

    while(i < cardinal) {

        if((2*i) + 1 < this->cardinal - 1 && pDatos[(2*i) + 1].n < pDatos[(2*i) + 2].n) {
            if(pDatos[i].n < pDatos[(2*i) + 2].n) {

                bufVar = pDatos[i];

                pDatos.Definir(i,pDatos[(2*i) + 2]);
                pDatos.Definir((2*i) + 2,bufVar);
                
            }
            i = (2*i) + 2;
        } else {
            if((2*i) + 1 < this->cardinal - 1 && pDatos[i].n < pDatos[(2*i) + 1].n) {

                bufVar = pDatos[i];

                pDatos.Definir(i,pDatos[(2*i) + 1]);
                pDatos.Definir((2*i) + 1,bufVar);
                
            }
            i = (2*i) + 1;
        }
    }
    return aux;
}

Lista<InfoCliente>::Iterador conjheap::DameElementos(){

    //se agrega elems

    int e = elems.Longitud();

    while(e > 0) {

        elems.Fin();

        e--;

    }


    int i = 0;

    while (i < this->cardinal) {
        elems.AgregarAtras(this->pDatos[i]);
        i++;
    }

    Lista<InfoCliente>::Iterador itLista = elems.CrearIt();

    return itLista;


}

bool conjheap::operator==(const conjheap& otro) const {
	
	if (this->tam == otro.tam && this->cardinal == otro.cardinal) {

		int i = 0;
		
		while(i < this->tam) {

			if (this->pDatos[i] != otro.pDatos[i]) {return false;}

			i++;
		}
		
		return true;
		
	}
	
	return false;

}
#endif // CONJHEAP_H
